﻿using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using net.xBei.Helper;

namespace net.xBei.WebApi.Models.Response {
    /// <summary>
    /// 向客户端返回文件
    /// </summary>
    public class FileResponse : IActionResult {
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; }
        /// <summary>
        /// 文件类型
        /// </summary>
        public string ContentType { get; }
        private readonly string file;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="file"></param>
        /// <param name="contentType"></param>
        /// <param name="fileName"></param>
        public FileResponse(string file, string contentType, string fileName) {
            this.file = file;
            ContentType = contentType;
            FileName = fileName;
        }
        /// <summary>
        /// 使用临时文件创建文件返回
        /// </summary>
        /// <param name="file"></param>
        /// <param name="contentType"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static IActionResult Create(string file, string contentType, string fileName) {
            return new FileStreamResult(File.OpenRead(file), contentType) {
                FileDownloadName = fileName,
                EnableRangeProcessing = true,
            };
        }
        /// <summary>
        /// 使用临时文件创建文件返回
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="contentType"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static IActionResult Create(byte[] buffer, string contentType, string fileName) {
            return new FileContentResult(buffer, contentType) {
                FileDownloadName = System.Web.HttpUtility.UrlEncode(fileName),
                EnableRangeProcessing = true,
            };
        }
        /// <summary>
        /// 使用临时文件创建文件返回
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="contentType"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static IActionResult Create(Stream stream, string contentType, string fileName) {
            return new FileStreamResult(stream, contentType) {
                FileDownloadName = System.Web.HttpUtility.UrlEncode(fileName),
                EnableRangeProcessing = true,
            };
        }
        /// <inheritdoc/>
        public async Task ExecuteResultAsync(ActionContext context) {
            context.HttpContext.Response.StatusCode = 200;
            context.HttpContext.Response.ContentType = ContentType;
            //context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{System.Web.HttpUtility.UrlEncode(FileName)}\"");
            context.HttpContext.Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{System.Web.HttpUtility.UrlEncode(FileName)}\"; filename*=UTF-8''{System.Web.HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8)}");
            using (var str = File.OpenRead(this.file)) {
                await str.CopyToAsync(context.HttpContext.Response.Body);
            }
            FileResponse.TaskRun(async (tmpFile) => {
                while (IOHelper.DeleteFile(tmpFile) == false) {
                    await Task.Delay(100);
                }
            }, this.file);
        }

        private static void TaskRun(Func<string, Task> action, string tmpFile) {
            Task.Run(async () => await action.Invoke(tmpFile));
        }
    }
}
